package com.export.config;

import common.entity.ReflexHandler;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 自动保存 方法url和声明类的映射关系
 *
 * @author yuanqinglong
 * @since 2021/3/3 9:08
 */
@Component
public class AutoMapping implements ApplicationContextAware {

    private final Map<String, ReflexHandler> handlerMapping = new HashMap<>(256);

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        String[] beanNames = BeanFactoryUtils.beanNamesForAnnotationIncludingAncestors(applicationContext, Controller.class);
        for (String beanName : beanNames) {
            Object controller = applicationContext.getBean(beanName);
            if (controller.getClass().isAnnotationPresent(Deprecated.class)) {
                continue;
            }
            Class<?> aClass = controller.getClass();
            for (Method method : aClass.getDeclaredMethods()) {
                if (method.isAnnotationPresent(RequestMapping.class)) {
                    ReflexHandler reflexHandler = new ReflexHandler(method, controller);
                    RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
                    if (requestMapping.value().length > 0) {
                        Stream.of(requestMapping.value()).forEach(url -> this.checkUrlPut(url, reflexHandler));
                    } else if (StringUtils.isNotBlank(requestMapping.name())) {
                        this.checkUrlPut(requestMapping.name(), reflexHandler);
                    }
                }
            }
        }
    }


    /**
     * 检查网址
     *
     * @param url url
     */
    private void checkUrlPut(String url, ReflexHandler reflexHandler) {
        if (handlerMapping.containsKey(url)) {
            throw new RuntimeException("url重复：" + url);
        }
        handlerMapping.put(url, reflexHandler);
    }

    @Bean
    public Map<String, ReflexHandler> handlerMapping() {
        return handlerMapping;
    }
}
